﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace WPFStorageClient
{
    using Microsoft.Samples.ServiceHosting.StorageClient;

    public class Container
    {
        private Object SyncObject = new Object();

        internal BlobContainer BlobContainer { get; private set; }
        public ObservableCollection<Blob> Blobs { get; set; }
        public ObservableCollection<Container> Prefixes { get; set; }
        public String Prefix { get; set; }

        internal bool GetStarted { get; set; }

        public String ContainerName
        {
            get
            {
                String strRet = null;
                if (!String.IsNullOrEmpty(Prefix))
                {
                    strRet = Prefix;
                }
                else if (BlobContainer != null)
                {
                    strRet = BlobContainer.ContainerName;
                }
                return strRet;
            }
        }

        public void CommonConstructor(BlobContainer container, String strPrefix)
        {
            Blobs = new ObservableCollection<Blob>();
            Prefixes = new ObservableCollection<Container>();
            BlobContainer = container;
            Prefix = strPrefix;
            GetStarted = false;
        }

        public Container(BlobContainer container)
        {
            CommonConstructor(container, null);
        }

        public Container(BlobContainer container, String strPrefix)
        {
            CommonConstructor(container, strPrefix);
        }

        //
        /// <summary>
        /// AddBlobDataToContainer -
        /// This part of the code always needs to be done on the UI thread. That is why it is seperate.
        /// </summary>
        /// <param name="blobData"></param>
        public void AddBlobDataToContainer(IEnumerable<Object> blobData)
        {
            if (System.Windows.Application.Current.Dispatcher.Thread !=
                    System.Threading.Thread.CurrentThread)
            {
                System.Windows.Application.Current.Dispatcher.BeginInvoke(
                            new Action<IEnumerable<Object>>(AddBlobDataToContainer),
                            new Object[] { blobData });
                return;
            }

            Blobs.Clear();
            Prefixes.Clear();
            // Ok, back on the app thread.
            foreach (Object obj in blobData)
            {
                BlobProperties blobProperties = obj as BlobProperties;
                if (blobProperties != null)
                {
                    Blobs.Add(new Blob(blobProperties, this));
                }
                else
                {
                    Prefixes.Add(new Container(BlobContainer, (String)obj));
                }

            }
        }

        //
        // Simple - only do a Get once for each container.
        //
        public void GetBlobData(Object o)
        {
            lock (SyncObject)
            {
                if (GetStarted)
                {
                    return;
                }
            }
            GetStarted = true;
            String strPrefix = Prefix;
            if (strPrefix == null)
            {
                strPrefix = String.Empty;
            }
            IEnumerable<Object> blobData = BlobContainer.ListBlobs(strPrefix, true);
            AddBlobDataToContainer(blobData);
        }

        //
        // RefreshBlobData
        //
        public void RefreshBlobData(Object o)
        {
            lock (SyncObject)
            {
                GetStarted = false;
            }
            GetBlobData(o);
        }
    }

    public class Blob
    {
        public Blob(BlobProperties blobProperties, Container container)
        {
            this.BlobProperties = blobProperties;
            this.Container = container;
        }

        internal BlobProperties BlobProperties { get; private set; }
        internal Container Container { get; private set; }
        public Uri Uri
        {
            get
            {
                Uri retUri = null;
                if (BlobProperties != null)
                {
                    retUri = BlobProperties.Uri;
                }
                return retUri;
            }
        }

        public String BlobName
        {
            get
            {
                String retName = null;
                if (BlobProperties != null)
                {
                    retName = BlobProperties.Name;
                }
                return retName;
            }
        }
    }

}
